#!/user/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import random

from PySide6.QtWidgets import *
from PySide6.QtCore import *
from PySide6.QtGui import *


class DesktopPet(QWidget):
    def __init__(self, parent=None, **kwargs) -> None:
        super(DesktopPet, self).__init__(parent)
        # 宠物大小
        self.petSize = (100, 100)
        # 鼠标
        self.is_follow_mouse = False
        # 窗体初始化
        self.initWin()
        # 托盘初始化
        self.initPall()
        # 宠物静态gif图加载
        self.initPetStaticImg()
        # 宠物正常待机, 实现随机切换动作
        self.petNormalAction()

    def initWin(self):
        """
        窗体初始化
        窗口属性: 窗口无标题栏且默认为最顶层
        :params
        :return
        """
        # FrameWindowHint: 无边框窗口
        # WindowStayOnTopHint: 窗口总显示在最上面
        # SubWindow: 新窗口部件是一个子窗口, 而无论窗口部件是否有父窗口部件
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
        self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint)
        self.setWindowFlag(Qt.WindowType.SubWindow)
        # setAutoFillBackground(): True表示自动填充, False表示透明背景
        self.setAutoFillBackground(False)
        # 窗口透明, 窗体空间不透明
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        # 重绘组件、刷新
        self.repaint()

    def initPall(self):
        """
        托盘初始化
        :params
        :return
        """
        iconPath = "res/Cherrim.png"
        # 设置右键显示最小化的菜单项
        # 菜单项退出绑定quit
        quit_action = QAction(u"退出", self, triggered=self.quit)
        # 菜单项显示绑定showing
        show_action = QAction(u"显示", self, triggered=self.showwin)
        # 隐藏
        hide_action = QAction(u"隐藏", self, triggered=self.hidewin)
        # 刷新宠物位置
        refresh_action = QAction(u"刷新", self, triggered=self.randomPosition)
        
        # 设置点击选项的图片
        show_action.setIcon(QIcon(iconPath))
        
        # 新建一个菜单项控件
        self.tray_icon_menu = QMenu(self)
        # 在菜单栏添加一个无子菜单的菜单项 显示
        self.tray_icon_menu.addAction(show_action)
        # 添加 隐藏
        self.tray_icon_menu.addAction(hide_action)
        # 添加 刷新
        self.tray_icon_menu.addAction(refresh_action)
        # 在菜单栏添加一个无子菜单的菜单项 退出
        self.tray_icon_menu.addAction(quit_action)
        
        # QSystemTrayIcon类为应用程序在系统托盘中提供一个图标
        self.tray_icon = QSystemTrayIcon(self)
        # 设置托盘化图标
        self.tray_icon.setIcon(QIcon(iconPath))
        # 设置托盘化菜单项
        self.tray_icon.setContextMenu(self.tray_icon_menu)
        # 展示
        self.tray_icon.show()

    def quit(self):
        self.close()
        sys.exit()

    def showwin(self):
        # setWindowOpacity() 
        # 设置窗体的透明度, 通过调整窗体透明度实现宠物的展示和隐藏
        self.setWindowOpacity(1)
        
    def hidewin(self):
        self.setWindowOpacity(0)

    def initPetStaticImg(self):
        """
        宠物静态图加载
        :params
        :return
        """
        # 对话框
        self.talkLabel = QLabel(self)
        # 对话框样式
        self.talkLabel.setStyleSheet(
            "font:15pt '楷体';"
            "border-width: 1px;"
            "color: skyblue;"
        )
        
        # 显示图片部分
        self.image = QLabel(self)
        # QMovie是一个可以存放动态视频的类，一般是配合QLabel使用的,可以用来存放GIF动态图
        self.movie = QMovie("res/normal/stt.gif")
        # 设置标签大小
        self.movie.setScaledSize(QSize(*self.petSize))
        # 将Qmovie在定义的image中显示
        self.image.setMovie(self.movie)
        self.movie.start()
        self.resize(*self.petSize)
        
        # 调用自定义的randomPosition, 使宠物出现位置随机
        self.randomPosition()
        
        # 展示
        self.show()
        
        # 将宠物正常待机状态的动图放入petGifList中
        self.petGifList = [
            f"res/normal/{i}"
            for i in os.listdir("res/normal")
        ]
        
        # 读取dialog文件中的对话
        self.dialog = [
            line 
            for line in self.readLineFromFile("res/dialog.txt")
        ]
        
    def randomPosition(self):
        """
        宠物随机位置
        :params
        :return
        """
        screen = QGuiApplication.primaryScreen().geometry()
        w, h = screen.width(), screen.height()
        w_p, h_p = self.petSize
        
        # width = ((w - w_p) * random.random())
        # height = ((h - h_p) - line_height)

        width = ((w - w_p) * random.random())
        height = ((h - h_p) * random.random())

        self.move(width, height)
        
    def readLineFromFile(self, path):
        """
        读取文件
        :params
            path: 路径
        :return
        """
        if not os.path.exists(path):
            return
        for line in open(path, 'r', encoding='utf-8'):
            yield line.strip()

    def petNormalAction(self):
        """
        宠物正常待机动作
        :params
        :return
        """
        # 定时随机做动作
        # 定时器设置
        self.timer = QTimer()
        # 执行
        self.timer.timeout.connect(self.randomAct)
        # 间隔时间
        self.timer.start(3000)
        # 宠物状态设置为正常
        self.condition = 0
        # 定时随机切换对话
        self.talkTimer = QTimer()
        self.talkTimer.timeout.connect(self.talk)
        self.talkTimer.start(3000)
        # 对话状态设置为常态
        self.talkCondition = 0
        # 宠物对话框
        self.talk()
        
    def randomAct(self):
        """
        随机切换动作
        condition 记录宠物状态, 
        为0时代表正常待机
        """
        if not self.condition:
            if self.is_follow_mouse == False:
                self.movie = QMovie(random.choice(self.petGifList))
                self.movie.setScaledSize(QSize(*self.petSize))
                self.image.setMovie(self.movie)
                self.movie.start()

        else:
            self.movie = QMovie(random.choice(self.petGifList))
            self.movie.setScaledSize(QSize(*self.petSize))
            self.image.setMovie(self.movie)
            self.movie.start()
            # 宠物设置为正常待机
            self.condition = 0
            self.talkCondition = 0
            
    def talk(self):
        """
        宠物对话框
        """
        if not self.talkCondition:
            if self.is_follow_mouse == False:
                self.talkLabel.setText(random.choice(self.dialog))
                self.talkLabel.setStyleSheet(
                    "font: bold;"
                    "font: 25pt '楷体';"
                    "color: white;"
                )
                self.talkLabel.adjustSize()
        else:
            # 为1显示别点我
            self.talkLabel.setText("别碰我...")
            self.talkLabel.setStyleSheet(
                "font: bold;"
                "font: 25pt '楷体';"
                "color: white;"
            )
            self.talkLabel.adjustSize()
            self.talkCondition = 0
        
    def mousePressEvent(self, event: QMouseEvent) -> None:
        self.condition = 1
        self.talkCondition = 1
        
        self.talk()
        self.randomAct()
        
        if event.button() == Qt.LeftButton:
            self.is_follow_mouse = True
        
        self.mouse_drag_pos = event.globalPos() - self.pos()
        event.accept()
        self.setCursor(QCursor(Qt.OpenHandCursor))
        
        return super().mousePressEvent(event)
    
    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        if Qt.LeftButton and self.is_follow_mouse:
            self.move(event.globalPos() - self.mouse_drag_pos)
        
        event.accept()
        
        return super().mouseMoveEvent(event)
    
    def mouseReleaseEvent(self, event: QMouseEvent) -> None:
        self.is_follow_mouse = False
        self.setCursor(QCursor(Qt.ArrowCursor))
        self.randomAct()
        self.talk()
        
        return super().mouseReleaseEvent(event)
    
    def contextMenuEvent(self, event: QContextMenuEvent) -> None:
        menu = QMenu(self)
        
        hideAction = menu.addAction(u"隐藏")
        quitAction = menu.addAction(u"退出")
        
        action = menu.exec_(self.mapToGlobal(event.pos()))
        if action == quitAction:
            self.quit()
        if action == hideAction:
            self.hidewin()
        
        return super().contextMenuEvent(event)
    
    def enterEvent(self, event: QEnterEvent) -> None:
        self.setCursor(Qt.ClosedHandCursor)
        
        return super().enterEvent(event)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    pet = DesktopPet()

    sys.exit(app.exec())
